package com.me.study.javaBasic.collection;

import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

/**
 * HashMap 快速失败
 *
 * @author ME
 * @date   2019/7/3
 */
public class TestHashMap {

    /**hash洪水攻击*/
    @Test
    public void hashFlooding() {
        // hashCode: 2112
        String aa = "Aa";
        String bb = "BB";
        // 2031744
        String aaAa = "AaAa";
        String aaBB = "AaBB";
        String bbAa = "BBAa";
        String bBBB = "BBBB";
        // hashCode: 96883
        String asd = "asd";
        System.out.println(aaAa.hashCode());
        HashMap<String, String> map = new HashMap<>(4);
        map.put(aa, aa);
        map.put(bb, bb);

        map.put(aaAa, aaAa);
        map.put(aaBB, aaBB);
        map.put(bbAa, bbAa);
        map.put(bBBB, bBBB);

        map.put(asd, asd);
        System.out.println(map);
    }

    public static void main(String[] args) {
        System.out.println("HashMap API:");
        Map<String, String> map = new HashMap<>();
        System.out.println("putIfAbsent(): 如果指定键不存在（或映射为 null），则 put \33[31;4m并返回 null\33[0m，否则返回当前值");
        assertNull("key不存在（或 value 为 null）才put，并返回 null", map.putIfAbsent("tom", "2333"));
        assertEquals("存在就不操作，并返回 当前value",
                "2333", map.putIfAbsent("tom", "999"));
        assertEquals("获取值",
                "2333", map.get("tom"));

        System.out.println("computeIfAbsent(): 如果指定键不存在（或映射为 null），则使用给定函数计算值后存入 Map，\33[31;4m并返回 计算结果\33[0m，否则返回当前值");
        assertEquals("key不存在（或 value 为 null）就计算并 put，再返回 计算结果",
                "hhh", map.computeIfAbsent("ljy", key -> {
                    System.out.println("computeIfAbsent Function 参数是 key：" + key);
                    return "hhh";
                }));
        assertEquals("存在就不操作，并返回 当前value",
                "hhh", map.computeIfAbsent("ljy", key -> "asdad"));
        assertEquals("获取值",
                "hhh", map.get("ljy"));

        Map<String, String> map1 = new HashMap<>();
        map1.put("BLACK", "黑色");
        map1.put("WHITE", "白色");
        map1.put("WHITE", "白色"); // 故意重复放一个
        map1.put("RED", "红色");

        // 遍历：HashMap 的存储是 无序的
        System.out.println("\nHashMap put()之后 无序: ");
        map1.forEach((k, v) -> System.out.print(k + ":" + v + "   "));

        try {
            // HashMap 会发生并发修改异常 ConcurrentModificationException
            System.out.println("\n\nHashMap: forEach() and put() -- 会并发修改异常 ConcurrentModificationException");
            map1.forEach((k, v) -> {
                if (k == "WHITE") {
                    map1.put("GREEN", "绿色");
                }
                System.out.print(k + ":" + v + "   ");
            });
        } catch (Exception e) {
            System.out.println("\nHashMap: forEach() and put() -- 会并发修改异常 ConcurrentModificationException");
        }

        // key 允许为 null
        System.out.println("\nHashMap： Key 允许为 'null'");
        map1.put(null,"未知");
    }

}
